Что такое современный веб-стек: Babel

Узнайте, что такое Babel и как его настроить

Что такое Вавилон?

Babel - это инструмент, который позволяет вам писать код Javascript, используя весь новейший синтаксис и функции, и запускать его в браузерах, которые могут не поддерживать эти функции. Babel - это транспилятор, который переведет ваш современный JS-код в старую версию Javscript, понятную большему количеству браузеров.

Babel часто встроен в инструменты, которые мы используем каждый день для создания современных веб-приложений (например, create-react-app), поэтому многие разработчики не имеют полного представления о том, что на самом деле делает этот инструмент. Это руководство предназначено для настройки конфигурации Babel по частям и является частью большой серии руководств по настройке вашей собственной пользовательской среды разработки.

Предпосылки

На вашем компьютере должен быть установлен Node.js и доступен с вашего терминала. Установка Node также автоматически установит npm, который вы будете использовать для установки Babel.

Откройте выбранный вами терминал. Если вы видите номера версий при выполнении двух команд ниже (ваши номера, вероятно, будут отличаться от этого примера), тогда вы готовы к работе:

node --version
> v15.5.0

npm --version
> 7.16.0

Инициализация проекта

Начнем с инициализации нового npm проекта. Выполните следующую команду, чтобы сгенерировать ее:

npm init -y

Флаг -y автоматически выберет значения по умолчанию для всего, что подходит в нашем примере.

Затем давайте создадим очень простой файл Javascript с использованием современного синтаксиса. Создайте файл с именем script.js со следующим кодом:

script.js

const x = 5;
let y;

const sampleFunction = () => "this is a return value";

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

const hasThree = [1, 2, 3].includes(3);
console.log(hasThree);

y ||= "a new value";
console.log(y);

В приведенном выше примере const, let, arrow function, includes метод массива и class - все это функции ES6, которые не будут работать должным образом в старых браузерах, таких как Internet Explorer 11 (которые, к сожалению, некоторые организации все еще широко используют даже в 2021 году).

Вы также можете поймать новенькое (с 2021 года) логическое ИЛИ задание. Это не будет работать в версиях Firefox до 79 и версиях Chrome до 85, и вообще не будет работать в IE11.

Итак, что мы можем сделать, чтобы запустить этот код в старых браузерах, не переписывая его самостоятельно?

Установка Babel

Для достижения нашей цели нам нужны три основных пакета, все они являются частью экосистемы Babel, но у каждого своя функция. Начните с выполнения следующей команды:

npm install @babel/core @babel/cli @babel/preset-env --save-dev

Давайте посмотрим, что делает каждый:

  • @babel/core - это основной движок, который знает, как преобразовать код на основе набора инструкций, которые ему даны.
  • @babel/cli - Это фактическая программа, которую мы собираемся запустить, чтобы запустить основной движок и вывести преобразованный файл Javascript.
  • @babel/preset-env - это предустановка, которая сообщает базовому движку, какие преобразования выполнять. Он смотрит на вашу среду (в нашем случае это будет наш package.json файл), чтобы определить, какие изменения необходимо внести в зависимости от браузеров, которые вы хотите поддерживать.

Нам нужно добавить пару значений в наш package.json файл:

  • browserslist - сообщает Babel, на какие браузеры мы нацелены. Чем старше / меньше они поддерживаются, тем больше работы и больше преобразований придется выполнить Babel, чтобы ваше приложение работало в этих браузерах. Синтаксис представляет собой простой массив строк. Вы можете узнать об этом здесь.
  • babel - Здесь мы определили все пресеты, которые мы будем использовать, а также любые параметры конфигурации, связанные с этими пресетами. Начнем с самого простого, @babel/preset-env

Итак, наш package.json файл должен выглядеть так:

package.json

{
  "devDependencies": {
    "@babel/cli": "^7.15.7",
    "@babel/core": "^7.15.5",
    "@babel/preset-env": "^7.15.6"
  },
  "browserslist": ["last 2 Chrome versions"],
  "babel": {
    "presets": [["@babel/preset-env"]]
  }
}

devDependencies уже должен быть там с вашего npm install. Два других свойства, описанных выше, вам нужно будет добавить самостоятельно.

Преобразование вашего кода

В самой базовой конфигурации babel преобразует ваш современный синтаксис в гораздо более широко поддерживаемый ES5.

Начнем с простого примера. Выполните следующую команду в корневом каталоге вашего проекта, содержащем ваш package.json файл и ваш script.js файл:

npx babel script.js --out-file script-transformed.js

Предполагая, что вы выполнили все инструкции до сих пор, вы должны увидеть новый созданный файл с именем script-transformed.js, который выглядит следующим образом:

script-transformed.js

"use strict";

const x = 5;
let y;

const sampleFunction = () => "this is a return value";

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

const hasThree = [1, 2, 3].includes(3);
console.log(hasThree);
y ||= "a new value";
console.log(y);

Не сильно отличается, правда? Кроме добавления строгого режима, практически ничего не изменилось.

Причина этого в том, как мы настроили нашу среду в package.json, куда @babel/plugin-env смотрит, чтобы решить, что ей делать.

package.json

...
"browserslist": [
  "last 2 Chrome versions"
],
...

Поскольку мы ориентируемся только на две самые последние версии Chrome, Babel знает, что у нас нет проблем, включая весь современный синтаксис JS, который мы хотим, он будет отлично работать в этих современных браузерах.

Но допустим, что мы обязаны поддерживать Internet Explorer 11. Мы не хотим менять способ написания нашего кода только для того, чтобы приспособиться к этому браузеру, но, к счастью, именно здесь Babel спасает положение. Обновите свой package.json, чтобы добавить IE11 в массив browserslist:

...
"browserslist": [
  "last 2 Chrome versions",
  "IE 11"
],
...

Теперь снова запустите эту команду:

npx babel script.js --out-file script-transformed.js

Взгляните на результат на этот раз:

script-transformed.js

"use strict";

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

var x = 5;
var y;

var sampleFunction = function sampleFunction() {
  return "this is a return value";
};

var Person = function Person(name, age) {
  _classCallCheck(this, Person);

  this.name = name;
  this.age = age;
};

var hasThree = [1, 2, 3].includes(3);
console.log(hasThree);
y || (y = "a new value");
console.log(y);

Это сильно отличается от нашего исходного файла! Обратите внимание, что почти все ES6 термины, которые мы обсуждали выше, исчезли, const заменен на var, наша стрелочная функция заменена синтаксисом function, а наш class был преобразован в базовый объект Javascript. Теперь мы можем взять этот script-transformed.js файл, обработать его до Internet Explorer 11, и он будет работать нормально ... почти!

У нас все еще есть одна небольшая проблема: метод includes не был преобразован. Это почему? Чтобы понять причину, нам сначала нужно понять полифиллы.

Полифиллы

Чтобы понять, зачем нам полифиллы, мы должны понимать разницу между новым syntax и новым functionality. includes метод новый functionality. За ним стоит своя логика, и простое изменение синтаксиса написания кода не объяснит старым браузерам, как должна работать логика метода includes.

Для новых функций, которые вводят новую функциональность, нам понадобится нечто, называемое полифилом. Полифиллы - это просто исходный код для такого метода, как includes, который вы связываете вместе со своим приложением, чтобы научить старые браузеры тому, как это работает.

Вам не нужно писать полифиллы самостоятельно, полифиллы практически для всех функций JS уже существуют и их легко включить. В будущих руководствах мы будем объединять и включать только те из них, которые нам нужны, но до тех пор мы можем просто включить библиотеку под названием core-js и мгновенно предоставить нашему приложению доступ ко всем современным функциям JS даже в старых браузерах.

Чтобы проверить это, загрузим в наше приложение всю core-js библиотеку. Поскольку мы еще не используем сборщик, мы просто загрузим уже объединенную и минифицированную версию из Интернета в наше приложение. Если у вас еще нет шаблона index.html, создайте этот файл в корневом каталоге проекта:

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script src="script-transformed.js"></script>
  </head>
  <body></body>
</html>

Начнем с попытки загрузить файл в IE11. Если на вашем компьютере нет Internet Explorer 11, вы можете просто следовать приведенному здесь примеру и просматривать снимки экрана. Этот пример работает на Windows 11, в котором полностью удален IE11. К счастью, Microsoft Edge поставляется с режимом IE 11 для тестирования приложений, требующих обратной совместимости.

Когда мы запускаем Babel и пытаемся загрузить наш script-transformed.js файл в IE11, мы получаем следующую ошибку на консоли:

Теперь давайте добавим библиотеку core-js к тегу <script> внутри <head> в нашем index.html. Вы можете найти самый последний URL минифицированного пакета здесь.

index.html

...
<head>
  <meta charset="UTF-8" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.18.1/minified.js"></script>
  <script src="script-transformed.js" defer></script>
</head>
...

Когда мы перезагружаем страницу в IE11, мы получаем:

Оно работает! Мы пишем современный Javascript и запускаем его в старом браузере динозавров! Замечательно!

Заключение

Теперь вы должны иметь довольно твердое представление об основах того, что такое Babel и как он работает. Конечно, есть еще много чего узнать. В будущих уроках мы более подробно рассмотрим еще два основных пресета, которые Babel поддерживает для транспиляции расширенных наборов Javascript: JSX и Typescript.

Когда мы начнем работать с webpack, мы также рассмотрим, как настроить Babel так, чтобы он импортировал только те функции из значительного core-js library, который вы фактически используете в своем приложении (например, Array.includes()), чтобы вам не нужно было полностью включать сама библиотека.

Однако прежде чем мы это сделаем, мы сначала рассмотрим основы каждого из этих инструментов по отдельности, после чего мы будем готовы посмотреть, как они объединяются, чтобы сформировать полный современный веб-стек.

Спасибо за чтение и следите за обновлениями!